home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-02-22 | 14.5 KB | 541 lines | [TEXT/KAHL] |
- /*
- File: SIGSimpleTest.c
-
- Contains: Sample source from Digital Signature chapter of Inside Mac
-
- Copyright: © 1993 by Apple Computer, Inc., all rights reserved.
-
- Notes: This code implements the sample source from Inside Mac.
- However, there are a few places where a small addition or
- adjustment was necessary to accomodate this sample. The
- changes simply have to do with displaying information in
- the console window for the DisplayCertificateSet function.
-
- What this sample does:
- • This sample first performs a signing operation on a simple
- buffer. The signature is stored in a global for convenience
- only, you will want to associate it with a document and
- most likely a specific part of a document.
-
- • The signature is then verified, and the SIGShowSigner dialog
- is presented.
-
- • Finally, the certificate set is output to the console.
-
- You will of course need to have a valid Signer file and an
- AOCE workstation to try this out.
- */
-
-
-
- // ——————————————— needed includes…
-
- #include <DigitalSignature.h> /* AOCE includes */
- #include <OCEErrors.h>
-
- #include <Memory.h> /* Mac managers */
- #include <Types.h>
- #include <Script.h>
- #include <Packages.h>
- #include <GestaltEqu.h>
- #include <console.h>
- #include <stdio.h>
-
-
- // ——————————————— defines…
-
- #define kBufferSize 128
- #define kReturn 0x0A
-
-
- // ——————————————— declarations…
-
- OSErr SaveSignature(SIGSignaturePtr signature, Size signatureSize);
- OSErr RetrieveSignature(SIGSignaturePtr *signature, Size *signatureSize);
- OSErr GetDataToProcess(Ptr *dataBuffer, Size *dataSize, Boolean *more);
-
- void DisplayCertNameAttribute(SIGNameAttributesInfo *name);
- void DisplaySignatureInfo(SIGSignerInfo *signerInfo);
- void DisplayCertificateInfo(SIGCertInfo *certInfo);
-
-
- // ——————————————— globals…
-
- SIGSignaturePtr gSIGSignature = nil;
-
-
- // ——————————————— core routines (this is what is in the documentation)…
-
- OSErr SignData()
- {
- OSErr error;
- Boolean moreToSign;
- Size signatureSize;
- Size dataSize;
- SIGSignaturePtr signature = nil;
- SIGContextPtr context = nil;
- Ptr dataBuffer = nil;
-
- do {
- // allocate a new context and prepare it for signing
-
- if (error = SIGNewContext(&context))
- break;
- if (error = SIGSignPrepare(context, (FSSpecPtr)nil, "\p", &signatureSize))
- break;
-
- // retrieve the data to be signed, in our application specific way,
- // and pass it to the toolbox to generate the digest for our signature.
- // NOTE: GetDataToProcess can be the same function for signing and verifying
-
- do {
- if (error = GetDataToProcess(&dataBuffer, &dataSize, &moreToSign))
- break;
- if (error = SIGProcessData(context, dataBuffer, dataSize))
- break;
- } while (moreToSign);
-
- if (error) // if encountered error above, bail all the way out
- break;
-
- // allocate a buffer of the size returned from SIGSignPrepare to hold our
- // signature then create the signature by passing the buffer to SIGSign
-
- signature = (SIGSignaturePtr)NewPtr(signatureSize);
- if (error = MemError())
- break;
- if (error = SIGSign(context, signature, (SIGStatusProcPtr)nil))
- break;
-
- // save the signature in our application specific way
-
- error = SaveSignature(signature, signatureSize);
- } while (0);
-
- // free the context now (forces user to re-enter their password next
- // time the SIGSignPrepare call is made)
-
- if (context) SIGDisposeContext(context);
-
- if (dataBuffer) DisposPtr(dataBuffer);
- if (signature) DisposPtr((Ptr)signature);
-
- return error;
- }
-
- OSErr VerifyData()
- {
- OSErr error;
- Boolean moreToVerify;
- Size signatureSize;
- Size dataSize;
- SIGSignaturePtr signature = nil;
- SIGContextPtr context = nil;
- Ptr dataBuffer = nil;
-
- do {
- // get the signature and its size from wherever our application saved it
-
- if (error = RetrieveSignature(&signature, &signatureSize))
- break;
-
- // allocate a new context and prepare it for verifying.
-
- if (error = SIGNewContext(&context))
- break;
- if (error = SIGVerifyPrepare(context, signature, signatureSize, (SIGStatusProcPtr)nil))
- break;
-
- // get the data to be verified, in our application specific way,
- // and pass it to the toolbox to generate a digest for our verification
- // NOTE: GetDataToProcess can be the same function for signing and verifying
-
- do {
- if (error = GetDataToProcess(&dataBuffer, &dataSize, &moreToVerify))
- break;
- if (error = SIGProcessData(context, dataBuffer, dataSize))
- break;
- } while (moreToVerify);
-
- if (error) // if encountered error above, bail all the way out
- break;
-
- // now, perform verification
-
- if (error = SIGVerify(context))
- break;
-
- // finally, display the person who signed the data. NOTE: you can call
- // SIGShowSigner even if a kSIGInvalidCredentialErr was returned from SIGVerify,
- // we really are being perhaps too strict here (depends on application)
-
- error = SIGShowSigner(context, "\p");
- } while (0);
-
- // free the context
-
- if (context) SIGDisposeContext(context);
-
- if (dataBuffer) DisposPtr(dataBuffer);
- if (signature) DisposPtr((Ptr)signature);
-
- return error;
- }
-
- OSErr DisplayCertificateSet(SIGContextPtr context)
- {
- unsigned short attrIndex;
- SIGNameAttributesInfo attrInfo;
- unsigned short certIndex;
- SIGCertInfo certInfo;
- SIGSignerInfo signerInfo;
- OSErr error;
-
- do {
- // get and display general signature information first
-
- if (error = SIGGetSignerInfo(context, &signerInfo))
- break;
- DisplaySignatureInfo(&signerInfo);
-
- // traverse entire certificate set and for each certificate,
- // display the SIGCertInfo for it then traverse the SIGNameAttributesInfo's
- // for that certificate and display them
-
- for (certIndex = kSIGSignerCertIndex; certIndex < signerInfo.certCount; certIndex++)
- {
- if (error = SIGGetCertInfo(context, certIndex, &certInfo))
- break;
- DisplayCertificateInfo(&certInfo);
- for (attrIndex = 0; attrIndex < certInfo.certAttributeCount; attrIndex++)
- {
- if (error = SIGGetCertNameAttributes(context, certIndex, attrIndex, &attrInfo))
- break;
- DisplayCertNameAttribute(&attrInfo);
- }
-
- // the line below is not in the Inside Mac sample code
- // since it is display dependent!!!
- printf("\n\n** Press any key to continue displaying certificates **");
- getchar();
- printf("\n\n");
- }
-
- // finally, display the root issuers' name attributes.
- // NOTE: there's no SIGCertInfo for the root, it's always valid etc…
-
- // also, the line below is not in the Inside Mac sample code
- // since it is display dependent!!!
- printf("—————————————————————— ROOT ISSUER ——————————————————————\n");
-
- for (attrIndex = 0; attrIndex < certInfo.issuerAttributeCount; attrIndex++)
- {
- if (error = SIGGetCertIssuerNameAttributes(context, certIndex-1, attrIndex, &attrInfo))
- break;
- DisplayCertNameAttribute(&attrInfo);
- }
- } while (0);
-
- return error;
- }
-
-
- // ——————————————— our stub utility routines…
-
- OSErr SaveSignature(SIGSignaturePtr signature, Size signatureSize)
- {
- OSErr error = noErr;
-
- if (gSIGSignature)
- DisposPtr(gSIGSignature);
-
- do {
- gSIGSignature = (SIGSignaturePtr)NewPtr(signatureSize);
- if (error = MemError())
- break;
- BlockMove(signature, gSIGSignature, signatureSize);
- if (error = MemError())
- break;
- } while (0);
-
- return error;
- }
-
- OSErr RetrieveSignature(SIGSignaturePtr *signature, Size *signatureSize)
- {
- // hack test code! We copy the signature here so it doesn't ever get
- // disposed of, makes testing code easier and faster
-
- *signatureSize = GetPtrSize(gSIGSignature);
- *signature = (SIGSignaturePtr)NewPtr(*signatureSize);
- BlockMove(gSIGSignature, *signature, *signatureSize);
-
- return MemError();
- }
-
- OSErr GetDataToProcess(Ptr *dataBuffer, Size *dataSize, Boolean *more)
- {
- OSErr error = noErr;
- Ptr tempPtr = nil;
-
- do {
- *more = false;
- if (*dataBuffer == nil)
- {
- *dataSize = kBufferSize;
- *dataBuffer = tempPtr = NewPtr(*dataSize);
- if (error = MemError())
- break;
- }
- else
- tempPtr = *dataBuffer;
- memset(tempPtr, 1, *dataSize);
- } while (0);
-
- return error;
- }
-
- void DisplayCertNameAttribute(SIGNameAttributesInfo *name)
- {
- p2cstr((StringPtr)&name->attribute);
- printf("%d %d %d %s\n", name->onNewLevel, name->attributeScript, name->attributeType, name->attribute);
- }
-
- void DisplaySignatureInfo(SIGSignerInfo *signerInfo)
- {
- Str255 time;
- Str255 date;
-
- printf("—————————————————————— SIGNER INFO ——————————————————————\n");
-
- IUDateString(signerInfo->signingTime, abbrevDate, date); // sign date
- p2cstr((StringPtr)&date);
- IUTimeString(signerInfo->signingTime, true, time); // sign time
- p2cstr((StringPtr)&time);
- printf("signing time: %s %s\n", &date, &time);
-
- printf("number of certs: %d\n", signerInfo->certCount); // num certs
-
- IUDateString(signerInfo->certSetStatusTime, abbrevDate, date); // sign date
- p2cstr((StringPtr)&date);
- IUTimeString(signerInfo->certSetStatusTime, true, time); // sign time
- p2cstr((StringPtr)&time);
- printf("cert set status time: %s %s\n", &date, &time);
-
- switch (signerInfo->signatureStatus) { // status
- case kSIGValid:
- printf("cert set status: valid\n"); break;
- case kSIGPending:
- printf("cert set status: pending\n"); break;
- case kSIGExpired:
- printf("cert set status: expired\n"); break;
- case kSIGInvalid:
- printf("cert set status: envalid\n"); break;
- default:
- printf("cert set status: UNKOWN!\n");
- }
-
- printf("—————————————————————————————————————————————————————————\n");
- }
-
- void DisplayCertificateInfo(SIGCertInfo *certInfo)
- {
- Str255 date;
-
- printf("——————————————————————— CERT INFO ———————————————————————\n");
-
- IUDateString(certInfo->startDate, abbrevDate, date); // start validity date
- p2cstr((StringPtr)&date);
- printf("start validity date: %s\n", &date);
-
- IUDateString(certInfo->endDate, abbrevDate, date); // end validity date
- p2cstr((StringPtr)&date);
- printf("end validity date: %s\n", &date);
-
- switch (certInfo->certStatus)
- {
- case kSIGValid:
- printf("cert status: valid\n"); break;
- case kSIGPending:
- printf("cert status: pending\n"); break;
- case kSIGExpired:
- printf("cert status: expired\n"); break;
- default:
- printf("cert status: UNKOWN!\n");
- }
-
- printf("cert attribute count: %d\n", certInfo->certAttributeCount);
- printf("issuer attribute count: %d\n", certInfo->issuerAttributeCount);
- p2cstr((StringPtr)&certInfo->serialNumber);
- printf("serial number: %s\n", &certInfo->serialNumber);
- printf("—————————————————————————————————————————————————————————\n");
- }
-
-
-
- // ——————————————— routines to get us up and running only (not necessarily exemplary)…
-
- void ClearConsole()
- {
- cgotoxy(1,1, stdout);
- ccleos(stdout);
- }
-
- OSErr Prep2DisplayCertificateSet()
- {
- OSErr error;
- Boolean more;
- Size signatureSize;
- Size dataSize;
- SIGSignaturePtr signature = nil;
- SIGContextPtr context = nil;
- Ptr dataBuffer = nil;
-
- do {
- // NOTE: For our sample purposes, we are doing another "fresh"
- // verify here so the functions can remain autonomous. This is by
- // no means an efficient little tool or anything. There must have
- // been a signature created however to get here!
-
- if (error = RetrieveSignature(&signature, &signatureSize))
- break;
- if (error = SIGNewContext(&context))
- break;
- if (error = SIGVerifyPrepare(context, signature, signatureSize, (SIGStatusProcPtr)nil))
- break;
- do {
- if (error = GetDataToProcess(&dataBuffer, &dataSize, &more))
- break;
- if (error = SIGProcessData(context, dataBuffer, dataSize))
- break;
- } while (more);
- if (error) // if encountered error above, bail all the way out
- break;
- if (error = SIGVerify(context))
- break;
-
- ClearConsole();
-
- // now instead of calling show signer, we will display the certificate
- // set ourselves to the user (not a great interface)…
-
- error = DisplayCertificateSet(context);
- } while (0);
-
- if (context) SIGDisposeContext(context);
-
- if (dataBuffer) DisposPtr(dataBuffer);
- if (signature) DisposPtr((Ptr)signature);
-
- return error;
- }
-
- char * MapErrorCode(error)
- {
- switch (error)
- {
- case kSIGOperationIncompatibleErr:
- return "context in user for another type of operation";
- case kSIGUserCanceled:
- return "user canceled operation";
- case kSIGVerifyFailedErr:
- return "verification failed";
- case kSIGInvalidCredentialErr:
- return "verified OK but certificate is invaid (expired or pending)";
- case kSIGIndexErr:
- return "index given for attribute or certificate is invalid";
- case kSIGSignerErr:
- return "problem with Signer";
- case kSIGPasswordErr:
- return "incorrect password";
- case kSIGInternalsErr:
- return "internal error";
- case kSIGContextPrepareErr:
- return "context already prepared";
- case kSIGNoDigestErr:
- return "no digest in the signature";
- case kSIGConversionErr:
- return "unable to decode an attribute";
- case kSIGSignerNotValidErr:
- return "Signer has expired or is pending, can't be used";
- case kSIGNoSignature:
- return "standard signature not found";
- default:
- return "Operating System Error";
- }
- }
-
- void ExecuteSampleCode()
- {
- char* process;
- OSErr error = noErr;
-
- do {
- ClearConsole();
- process = "SignData";
- printf("Try out %s function…\n", process);
- if (error = SignData())
- break;
- ClearConsole();
- process = "VerifyData";
- printf("Try out %s function…\n", process);
- if (error = VerifyData())
- break;
- ClearConsole();
- process = "DisplayCertificateSet";
- printf("Try out %s function…\n", process);
- if (error = Prep2DisplayCertificateSet())
- break;
- printf("\n\n** Press <return> to exit **");
- } while (0);
-
- if (error)
- printf("### %s error %d %s", process, error, MapErrorCode(error));
- }
-
- void PrepareConsole()
- {
- char c;
-
- console_options.title = "\pDigital Signature Sample Code";
- console_options.top = 40;
- console_options.left = 3;
- console_options.nrows = 27;
- console_options.ncols = 83;
- cshow(stdout);
- csetmode(C_NOECHO /*C_CBREAK*/, stdout);
-
- ClearConsole();
- printf("This little application simply executes the sample code\n");
- printf("found in the Digital Signature chapter of Inside Mac\n");
- printf("© 1990-1993 Apple Computer, Inc.\n\n");
-
- printf("Press return key to run the Inside Mac sample code,\n");
- printf("any other key will cancel:");
- c = getchar();
-
- if (c != kReturn)
- ExitToShell();
- }
-
- void main ()
- {
- long ignore;
-
- PrepareConsole();
-
- InitGraf(&thePort);
- InitFonts();
- InitWindows();
- InitDialogs(nil);
- InitCursor();
-
- if (Gestalt(gestaltDigitalSignatureVersion, &ignore) == noErr)
- {
- ExecuteSampleCode();
- if (gSIGSignature)
- DisposPtr((Ptr)gSIGSignature);
- }
- else
- printf("\n\n### Digital Signature toolbox not available!");
- }